home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 1998 June
/
SGI Freeware 1998 June.iso
/
dist
/
fw_ATxgopher.idb
/
usr
/
freeware
/
src
/
xgopher.1.3
/
jobs.c.z
/
jobs.c
Wrap
C/C++ Source or Header
|
1998-01-21
|
7KB
|
335 lines
/* jobs.c
get some idea of the jobs spawned by Xgopher */
/*---------------------------------------------------------------*/
/* Xgopher version 1.3 08 April 1993 */
/* version 1.2 20 November 1992 */
/* version 1.1 20 April 1992 */
/* version 1.0 04 March 1992 */
/* X window system client for the University of Minnesota */
/* Internet Gopher System. */
/* Allan Tuchman, University of Illinois at Urbana-Champaign */
/* Computing and Communications Services Office */
/* Copyright 1992, 1993 by */
/* the Board of Trustees of the University of Illinois */
/* Permission is granted to freely copy and redistribute this */
/* software with the copyright notice intact. */
/*---------------------------------------------------------------*/
#ifdef DEBUG
void listJobs(
);
#endif
#include <stdio.h>
#include "conf.h"
#include "gopher.h"
#include "osdep.h"
#include "jobs.h"
#include <signal.h>
#include <sys/wait.h>
#include <sys/time.h>
#ifndef ISCX
#include <sys/resource.h>
#endif
#if defined(SYSV) || defined(SVR4) || defined(__convex__) || defined(__bsdi__) || defined(sgi) || defined(linux) || defined(DEC)
#define WAITSTATUS_INT
#else
#undef WAITSTATUS_INT
#endif
static jobList *jobs = (jobList *) NULL;
/* childIsGone
handle signal noting the termination of a child process */
void
childIsGone()
{
waitOnChildren();
#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif
/* some Unix flavors need to reset the signal handler
after one is delivered. */
signal (SIGCLD, childIsGone);
}
/* addJob
add the given pid to the internal job data structures */
void
addJob(t, pid)
char t;
PID_TYPE pid;
{
static firstTime = TRUE;
jobList *j=(jobList *) malloc(sizeof(jobList));
if (firstTime) {
/* set signal handler to catch child processes, note their
termination (prevent zombie status), and remove them from
the job queue. */
#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif
signal (SIGCLD, childIsGone);
firstTime = FALSE;
}
j->jobType = t;
j->pid = pid;
j->next = jobs;
jobs = j;
}
/* removeJob
remove the given pid from the internal job data structures */
BOOLEAN
removeJob(pid)
PID_TYPE pid;
{
jobList *j, *jp;
jp = NULL;
for (j=jobs; (j != (jobList *) NULL && j->pid != pid); j=j->next){
jp = j;
}
if (j != NULL) { /* pid in list */
#ifdef DEBUG
fprintf (stderr, "Remove process %d (type %c)\n",
j->pid, j->jobType);
#endif /* DEBUG */
if (jp == NULL) { /* first element */
jobs = j->next;
} else {
jp->next = j->next;
}
free(j);
return TRUE;
} else {
return FALSE;
}
}
/* findJobPID
return the item type of the child with the supplied pid */
char
findJobPID(pid)
PID_TYPE pid;
{
jobList *j;
for (j=jobs; (j != (jobList *) NULL && j->pid != pid); j=j->next){
}
return (j == NULL) ? NO_TYPE : j->jobType;
}
/* findJobType
return the pid of the first child that matches the supplied type */
PID_TYPE
findJobType(t)
char t;
{
jobList *j;
for (j=jobs; (j != (jobList *) NULL && j->jobType != t); j=j->next){
}
return (j == NULL ? NO_JOB: j->pid);
}
/* killItemProcess
terminate a specific child process */
void
killItemProcess(pid)
PID_TYPE pid;
{
#ifdef DEBUG
fprintf (stderr, "killing process %d\n", pid);
#endif /* DEBUG */
if (pid > 1) kill(pid, KILL_SIGNAL);
waitOnChildren();
}
/* killAllItemType
terminate all items that match the supplied type */
void
killAllItemType(t)
char t;
{
jobList *j, *nj;
/* WARNING: the kill will do a wait(2), then remove the
job from this job queue. So in stepping through the elements
be sure never to reference a jobList* after the kill.
In particular, grab the "next" field before killing. */
#ifdef DEBUG
fprintf (stderr, "killing processes for item type %c\n", t);
listJobs();
#endif /* DEBUG */
nj = jobs;
while ( nj != (jobList *) NULL ){
j = nj;
nj = j->next;
if (j->jobType == t) {
killItemProcess(j->pid);
}
}
}
/* killAllItemProcesses
terminate all child processes. */
void
killAllItemProcesses()
{
jobList *j, *nj;
/* WARNING: the kill will do a wait(2), then remove the
job from this job queue. So in stepping through the elements
be sure never to reference a jobList* after the kill.
In particular, grab the "next" field before killing. */
#ifdef DEBUG
fprintf (stderr, "killing all processes\n");
listJobs();
#endif /* DEBUG */
#ifdef DEBUG
fprintf (stderr, "start: jobs=0x%x\n", jobs);
#endif /* DEBUG */
nj = jobs;
while ( nj != (jobList *) NULL ) {
j = nj;
nj = j->next;
#ifdef DEBUG
fprintf (stderr, "next iter: j=0x%x, nj=0x%x\n", j, nj);
#endif /* DEBUG */
killItemProcess(j->pid);
}
}
/* waitForJob
block until a specified job is completed */
void
waitForJob(waitPID)
PID_TYPE waitPID;
{
PID_TYPE donePID;
#ifndef WAITSTATUS_INT
union wait status;
#else
int status;
#endif /* ! WAITSTATUS_INT */
do {
donePID = wait(&status);
#ifdef DEBUG
fprintf (stderr, "Process %d is done\n", donePID);
#endif /* DEBUG */
if (donePID != (PID_TYPE) 0) {
removeJob(donePID);
}
} while (donePID != waitPID);
}
/* waitOnChildren
handle request or signal noting the termination of a child process */
void
waitOnChildren()
{
PID_TYPE donePID;
#ifndef WAITSTATUS_INT
union wait status;
#else
int status;
#endif /* ! WAITSTATUS_INT */
#if !defined(macII) && !defined(CRAY) && !defined(SVR4) && !defined(SYSV)
#define WAIT3
struct rusage rusage;
#endif /* MacII, CRAY, SVR4, SYSV */
do {
#if defined(macII)
donePID = wait3(&status, WNOHANG, NULL);
#else /* not macII */
# if !defined(WAIT3)
donePID = waitpid(-1, &status, WNOHANG);
# else /* use wait3 call for others */
donePID = wait3(&status, WNOHANG, &rusage);
# endif /* other */
#endif /* */
#ifdef DEBUG
fprintf (stderr, "Process %d is done\n", donePID);
#endif /* DEBUG */
if (donePID > (PID_TYPE) 0) {
#ifndef WIFEXITED
#define WIFEXITED(x) (! ((x) & 0xff))
#endif
if (WIFEXITED(status)) {
removeJob(donePID);
}
}
} while (donePID > (PID_TYPE) 0);
}
#ifdef DEBUG
void
listJobs()
{
jobList *j;
fprintf (stderr, "Active processes started by Xgopher\n");
for (j=jobs; j != (jobList *) NULL; j=j->next){
fprintf (stderr, " pid: %6d Xgopher item type \'%c\'\n",
j->pid, j->jobType);
}
fprintf (stderr, "End of active process list\n");
}
#endif